home *** CD-ROM | disk | FTP | other *** search
/ Gold Medal Software 2 / Gold Medal Software Volume 2 (Gold Medal) (1994).iso / prog / tge129c.arj / SOURCE.ARJ / 1024X768.ASM next >
Assembly Source File  |  1993-08-20  |  39KB  |  1,968 lines

  1. ; 1024x768x256 (requires register-compatible VGA+)
  2. ; Loadable driver for The Graphics Engine
  3. ; Copyright (c) 1993 by Matthew Hildebrand
  4. ; Turbo Assembler syntax
  5. ; Portions by John Bridges
  6.  
  7. IDEAL
  8. P486N            ; 386 code, but we want 486 alignment
  9. MODEL LARGE
  10.  
  11.  
  12. SCREEN_WIDE    =    1024
  13. SCREEN_DEEP    =    768
  14. NUM_COLOURS    =    256
  15.  
  16.  
  17.         CODESEG
  18.         ORG    0
  19.  
  20. ;*** Signature
  21.             db    'TGE3'
  22. ;*** Non-I/O functions
  23. _initGraphics        dw    initGraphics        ; initGraphics
  24.             dw    ?
  25. _deInitGraphics        dw    0            ; deInitGraphics
  26.             dw    ?
  27. _setPaletteReg        dw    setPaletteReg        ; setPaletteReg
  28.             dw    ?
  29. _getPaletteReg        dw    getPaletteReg        ; getPaletteReg
  30.             dw    ?
  31. _setBlockPalette    dw    setBlockPalette        ; setBlockPalette
  32.             dw    ?
  33. _getBlockPalette    dw    getBlockPalette        ; getBlockPalette
  34.             dw    ?
  35. _colourCloseTo        dw    0            ; colourCloseTo
  36.             dw    ?
  37. _colourCloseToX        dw    0            ; colourCloseToX
  38.             dw    ?
  39. _imageSize        dw    0            ; imageSize
  40.             dw    ?
  41. _imageSizeDim        dw    0            ; imageSizeDim
  42.             dw    ?
  43. _setPage        dw    0            ; setPage (not implemented yet)
  44.             dw    ?
  45.  
  46. ;*** Currently active I/O functions (filled in by loadGraphDriver())
  47.             dd    20    DUP(?)
  48.  
  49. ;*** Input functions
  50. _getImage_scr        dw    0            ; getImage
  51.             dw    ?
  52. _getImage_mem        dw    0
  53.             dw    ?
  54. _getLine_scr        dw      getLine_scr              ; getLine
  55.             dw    ?
  56. _getLine_mem        dw    getLine_mem
  57.             dw    ?
  58. _getPixel_scr        dw    getPixel_scr        ; getPixel
  59.             dw    ?
  60. _getPixel_mem        dw    getPixel_mem
  61.             dw    ?
  62.  
  63. ;*** Output functions
  64. _putImage_scr_copy    dw    0            ; putImage
  65.             dw    ?
  66. _putImage_scr_and    dw    0
  67.             dw    ?
  68. _putImage_scr_not    dw    0
  69.             dw    ?
  70. _putImage_scr_or    dw    0
  71.             dw    ?
  72. _putImage_scr_xor    dw    0
  73.             dw    ?
  74. _putImage_mem_copy    dw    0
  75.             dw    ?
  76. _putImage_mem_and    dw    0
  77.             dw    ?
  78. _putImage_mem_not    dw    0
  79.             dw    ?
  80. _putImage_mem_or    dw    0
  81.             dw    ?
  82. _putImage_mem_xor    dw    0
  83.             dw    ?
  84. _putImageInv_scr_copy    dw    0            ; putImageInv
  85.             dw    ?
  86. _putImageInv_scr_and    dw    0
  87.             dw    ?
  88. _putImageInv_scr_not    dw      0
  89.             dw    ?
  90. _putImageInv_scr_or    dw      0
  91.             dw    ?
  92. _putImageInv_scr_xor    dw    0
  93.             dw    ?
  94. _putImageInv_mem_copy    dw    0
  95.             dw    ?
  96. _putImageInv_mem_and    dw    0
  97.             dw    ?
  98. _putImageInv_mem_not    dw    0
  99.             dw    ?
  100. _putImageInv_mem_or    dw    0
  101.             dw    ?
  102. _putImageInv_mem_xor    dw    0
  103.             dw    ?
  104. _putLine_scr_copy          dw    putLine_scr_copy    ; putLine
  105.             dw    ?
  106. _putLine_scr_and          dw      0
  107.             dw    ?
  108. _putLine_scr_not          dw      0
  109.             dw    ?
  110. _putLine_scr_or          dw      0
  111.             dw    ?
  112. _putLine_scr_xor          dw    0
  113.             dw    ?
  114. _putLine_mem_copy    dw      putLine_mem_copy
  115.             dw    ?
  116. _putLine_mem_and    dw      0
  117.             dw    ?
  118. _putLine_mem_not    dw      0
  119.             dw    ?
  120. _putLine_mem_or        dw      0
  121.             dw    ?
  122. _putLine_mem_xor    dw    0
  123.             dw    ?
  124. _putLineInv_scr_copy       dw    0            ; putLineInv
  125.             dw    ?
  126. _putLineInv_scr_and       dw    0
  127.             dw    ?
  128. _putLineInv_scr_not       dw    0
  129.             dw    ?
  130. _putLineInv_scr_or       dw    0
  131.             dw    ?
  132. _putLineInv_scr_xor       dw    0
  133.             dw    ?
  134. _putLineInv_mem_copy    dw    0
  135.             dw    ?
  136. _putLineInv_mem_and    dw    0
  137.             dw    ?
  138. _putLineInv_mem_not    dw    0
  139.             dw    ?
  140. _putLineInv_mem_or    dw    0
  141.             dw    ?
  142. _putLineInv_mem_xor    dw    0
  143.             dw    ?
  144. _putPixel_scr_copy    dw    putPixel_scr_copy    ; putPixel
  145.             dw    ?
  146. _putPixel_scr_and    dw      0
  147.             dw    ?
  148. _putPixel_scr_not    dw      0
  149.             dw    ?
  150. _putPixel_scr_or    dw      0
  151.             dw    ?
  152. _putPixel_scr_xor    dw    0
  153.             dw    ?
  154. _putPixel_mem_copy    dw    putPixel_mem_copy
  155.             dw    ?
  156. _putPixel_mem_and    dw      putPixel_mem_and
  157.             dw    ?
  158. _putPixel_mem_not    dw      putPixel_mem_not
  159.             dw    ?
  160. _putPixel_mem_or    dw      putPixel_mem_or
  161.             dw    ?
  162. _putPixel_mem_xor    dw    putPixel_mem_xor
  163.             dw    ?
  164. _line_scr_copy        dw    0            ; line
  165.             dw    ?
  166. _line_scr_and        dw      0
  167.             dw    ?
  168. _line_scr_not        dw      0
  169.             dw    ?
  170. _line_scr_or        dw      0
  171.             dw    ?
  172. _line_scr_xor        dw    0
  173.             dw    ?
  174. _line_mem_copy        dw    0
  175.             dw    ?
  176. _line_mem_and        dw    0
  177.             dw    ?
  178. _line_mem_not        dw    0
  179.             dw    ?
  180. _line_mem_or        dw    0
  181.             dw    ?
  182. _line_mem_xor        dw    0
  183.             dw    ?
  184. _horizLine_scr_copy    dw    horizLine_scr_copy      ; horizLine
  185.             dw    ?
  186. _horizLine_scr_and    dw      0
  187.             dw    ?
  188. _horizLine_scr_not    dw      0
  189.             dw    ?
  190. _horizLine_scr_or    dw      0
  191.             dw    ?
  192. _horizLine_scr_xor    dw    0
  193.             dw    ?
  194. _horizLine_mem_copy    dw    horizLine_mem_copy
  195.             dw    ?
  196. _horizLine_mem_and    dw      0
  197.             dw    ?
  198. _horizLine_mem_not    dw      0
  199.             dw    ?
  200. _horizLine_mem_or    dw      0
  201.             dw    ?
  202. _horizLine_mem_xor    dw    0
  203.             dw    ?
  204. _vertLine_scr_copy    dw    0             ; vertLine
  205.             dw    ?
  206. _vertLine_scr_and    dw    0
  207.             dw    ?
  208. _vertLine_scr_not    dw    0
  209.             dw    ?
  210. _vertLine_scr_or    dw    0
  211.             dw    ?
  212. _vertLine_scr_xor    dw    0
  213.             dw    ?
  214. _vertLine_mem_copy    dw    0
  215.             dw    ?
  216. _vertLine_mem_and    dw    0
  217.             dw    ?
  218. _vertLine_mem_not    dw    0
  219.             dw    ?
  220. _vertLine_mem_or    dw    0
  221.             dw    ?
  222. _vertLine_mem_xor    dw    0
  223.             dw    ?
  224. _drawRect_scr_copy    dw    0            ; drawRect
  225.             dw    ?
  226. _drawRect_scr_and    dw    0
  227.             dw    ?
  228. _drawRect_scr_not    dw    0
  229.             dw    ?
  230. _drawRect_scr_or    dw    0
  231.             dw    ?
  232. _drawRect_scr_xor    dw    0
  233.             dw    ?
  234. _drawRect_mem_copy    dw    0
  235.             dw    ?
  236. _drawRect_mem_and    dw    0
  237.             dw    ?
  238. _drawRect_mem_not    dw    0
  239.             dw    ?
  240. _drawRect_mem_or    dw    0
  241.             dw    ?
  242. _drawRect_mem_xor    dw    0
  243.             dw    ?
  244. _filledRect_scr_copy    dw    0            ; filledRect
  245.             dw    ?
  246. _filledRect_scr_and    dw      0
  247.             dw    ?
  248. _filledRect_scr_not    dw      0
  249.             dw    ?
  250. _filledRect_scr_or    dw      0
  251.             dw    ?
  252. _filledRect_scr_xor    dw    0
  253.             dw    ?
  254. _filledRect_mem_copy    dw    0
  255.             dw    ?
  256. _filledRect_mem_and    dw    0
  257.             dw    ?
  258. _filledRect_mem_not    dw    0
  259.             dw    ?
  260. _filledRect_mem_or    dw    0
  261.             dw    ?
  262. _filledRect_mem_xor    dw    0
  263.             dw    ?
  264. _clearGraphics_scr_copy    dw    0            ; clearGraphics
  265.             dw    ?
  266. _clearGraphics_scr_and    dw      0
  267.             dw    ?
  268. _clearGraphics_scr_not    dw      0
  269.             dw    ?
  270. _clearGraphics_scr_or    dw      0
  271.             dw    ?
  272. _clearGraphics_scr_xor    dw    0
  273.             dw    ?
  274. _clearGraphics_mem_copy    dw    0
  275.             dw    ?
  276. _clearGraphics_mem_and    dw    0
  277.             dw    ?
  278. _clearGraphics_mem_not    dw    0
  279.             dw    ?
  280. _clearGraphics_mem_or    dw    0
  281.             dw    ?
  282. _clearGraphics_mem_xor    dw    0
  283.             dw    ?
  284. _ellipse_scr_copy    dw    0            ; ellipse
  285.             dw    ?
  286. _ellipse_scr_and    dw    0
  287.             dw    ?
  288. _ellipse_scr_not    dw    0
  289.             dw    ?
  290. _ellipse_scr_or        dw    0
  291.             dw    ?
  292. _ellipse_scr_xor    dw    0
  293.             dw    ?
  294. _ellipse_mem_copy    dw    0
  295.             dw    ?
  296. _ellipse_mem_and    dw    0
  297.             dw    ?
  298. _ellipse_mem_not    dw    0
  299.             dw    ?
  300. _ellipse_mem_or        dw    0
  301.             dw    ?
  302. _ellipse_mem_xor    dw    0
  303.             dw    ?
  304. _filledEllipse_scr_copy    dw    0            ; filledEllipse
  305.             dw    ?
  306. _filledEllipse_scr_and    dw    0
  307.             dw    ?
  308. _filledEllipse_scr_not    dw    0
  309.             dw    ?
  310. _filledEllipse_scr_or    dw    0
  311.             dw    ?
  312. _filledEllipse_scr_xor    dw    0
  313.             dw    ?
  314. _filledEllipse_mem_copy    dw    0
  315.             dw    ?
  316. _filledEllipse_mem_and    dw    0
  317.             dw    ?
  318. _filledEllipse_mem_not    dw    0
  319.             dw    ?
  320. _filledEllipse_mem_or    dw    0
  321.             dw    ?
  322. _filledEllipse_mem_xor    dw    0
  323.             dw    ?
  324. _circle_scr_copy    dw    0            ; circle
  325.             dw    ?
  326. _circle_scr_and        dw    0
  327.             dw    ?
  328. _circle_scr_not        dw    0
  329.             dw    ?
  330. _circle_scr_or        dw    0
  331.             dw    ?
  332. _circle_scr_xor        dw    0
  333.             dw    ?
  334. _circle_mem_copy    dw    0
  335.             dw    ?
  336. _circle_mem_and        dw    0
  337.             dw    ?
  338. _circle_mem_not        dw    0
  339.             dw    ?
  340. _circle_mem_or        dw    0
  341.             dw    ?
  342. _circle_mem_xor        dw    0
  343.             dw    ?
  344. _filledCircle_scr_copy    dw    0            ; filledCircle
  345.             dw    ?
  346. _filledCircle_scr_and    dw    0
  347.             dw    ?
  348. _filledCircle_scr_not    dw    0
  349.             dw    ?
  350. _filledCircle_scr_or    dw    0
  351.             dw    ?
  352. _filledCircle_scr_xor    dw    0
  353.             dw    ?
  354. _filledCircle_mem_copy    dw    0
  355.             dw    ?
  356. _filledCircle_mem_and    dw    0
  357.             dw    ?
  358. _filledCircle_mem_not    dw    0
  359.             dw    ?
  360. _filledCircle_mem_or    dw    0
  361.             dw    ?
  362. _filledCircle_mem_xor    dw    0
  363.             dw    ?
  364. _fillRegion_scr_copy    dw    0            ; fillRegion
  365.             dw    ?
  366. _fillRegion_scr_and    dw    0
  367.             dw    ?
  368. _fillRegion_scr_not    dw    0
  369.             dw    ?
  370. _fillRegion_scr_or    dw    0
  371.             dw    ?
  372. _fillRegion_scr_xor    dw    0
  373.             dw    ?
  374. _fillRegion_mem_copy    dw    0
  375.             dw    ?
  376. _fillRegion_mem_and    dw    0
  377.             dw    ?
  378. _fillRegion_mem_not    dw    0
  379.             dw    ?
  380. _fillRegion_mem_or    dw    0
  381.             dw    ?
  382. _fillRegion_mem_xor    dw    0
  383.             dw    ?
  384. _fillLine_scr_copy    dw    0            ; fillLine
  385.             dw    ?
  386. _fillLine_scr_and    dw      0
  387.             dw    ?
  388. _fillLine_scr_not    dw      0
  389.             dw    ?
  390. _fillLine_scr_or    dw      0
  391.             dw    ?
  392. _fillLine_scr_xor    dw    0
  393.             dw    ?
  394. _fillLine_mem_copy    dw    0
  395.             dw    ?
  396. _fillLine_mem_and    dw      0
  397.             dw    ?
  398. _fillLine_mem_not    dw      0
  399.             dw    ?
  400. _fillLine_mem_or    dw      0
  401.             dw    ?
  402. _fillLine_mem_xor    dw    0
  403.             dw    ?
  404. ;*** Mode information
  405. scrnMaxX        dw    1023    ; physical dimensions
  406. scrnMaxY        dw    767
  407. maxColour        dw    255    ; maximum colour number
  408. xRatio                   dw    4    ; aspect ratio 4:3 (1024:768 in
  409. yRatio            dw    3    ;   lowest terms)
  410. bitsPerPixel        dw    8    ; 8 bits per pixel
  411. inMaxX            dw    1023    ; current input screen dimensions
  412. inMaxY            dw    767
  413. outMaxX            dw    1023    ; current output screen dimensions
  414. outMaxY            dw    767
  415. inScreenWide        dw    ?    ; needed only for virtual screens
  416. outScreenWide        dw    ?
  417. ;*** Viewport information
  418. inViewportULX        dw    0
  419. inViewportULY        dw    0
  420. inViewportLRX        dw    1023
  421. inViewportLRY        dw    767
  422. outViewportULX        dw    0
  423. outViewportULY        dw    0
  424. outViewportLRX        dw    1023
  425. outViewportLRY        dw    767
  426. ;*** Paging information
  427. pagingSupported        dw    ?    ; not implemented yet
  428. curPage            dw    ?    ; not implemented yet
  429. maxPage            dw    ?    ; not implemented yet
  430. ;*** Force (image width MOD imageWideAdjust) = 0.
  431. imageWideAdjust        dw    ?    ; not implemented yet
  432. ;*** Current and screen addresses
  433.     LABEL    inAddr    DWORD        ; current input address
  434. inOff    dw    0
  435. inSeg    dw    0A000h
  436.     LABEL    outAddr    DWORD        ; current output address
  437. outOff    dw    0
  438. outSeg    dw    0A000h
  439.     LABEL    scrAddr    DWORD        ; screen address
  440. scrOff    dw    0
  441. scrSeg    dw    0A000h
  442. ;*** Copyright string
  443.     db    'The Graphics Engine -- Copyright (c) 1993 by Matthew Hildebrand'
  444.  
  445.  
  446. inited        db    0
  447. colourPalette    db    768    DUP(?)
  448. lineOffs    dw    SCREEN_DEEP    DUP(?)
  449. bankNum        dw    SCREEN_DEEP    DUP(?)
  450. bankChanges    dw    SCREEN_DEEP    DUP(?)
  451. curBank        dw    ?
  452. screenWide    dw    ?
  453.  
  454. bankadr        dw    OFFSET _nobank
  455. vgamem        dw    ?
  456. bksize        dw    ?
  457. bksizeShl10Dec    dw    ?
  458. retval        dw    ?        ; first return value from whichVGA()
  459. scanline    dw    ?
  460.  
  461. aheadb        dw    ?
  462. ativga        dw    ?
  463. chipstech    dw    ?
  464. everex        dw    ?
  465. oak067        dw    ?
  466. t8900        dw    ?
  467. tseng4        dw    ?
  468. vesa        dw    ?
  469.  
  470.  
  471. ; VESA information
  472.     STRUC    vgainfo
  473. VESASignature    db    4 dup (?)    ; 4 signature bytes
  474. VESAVersion    dw    ?        ; VESA version number
  475. OEMStringPtr    dd    ?        ; Pointer to OEM string
  476. Capabilities    db    4 dup (?)    ; Capabilities of the video environment
  477. VideoModePtr    dd    ?        ; Pointer to supported Super VGA modes
  478.     ENDS
  479.     STRUC    vesamode
  480. ModeAttributes    dw    ?    ; mode attributes
  481. WinAAttributes    db    ?    ; window A attributes
  482. WinBAttributes    db    ?    ; window B attributes
  483. WinGranularity    dw    ?    ; window granularity
  484. WinSize        dw    ?    ; window size
  485. WinASegment    dw    ?    ; window A start segment
  486. WinBSegment    dw    ?    ; window B start segment
  487. WinFuncPtr    dd    ?    ; pointer to window function
  488. BytesPerLine    dw    ?    ; bytes per scan line
  489. ;
  490. ; optional information (provided if bit D1 of ModeAttributes is set)
  491. ;
  492. XResolution    dw    ?    ; horizontal resolution
  493. YResolution    dw    ?    ; vertical resolution
  494. XCharSize    db    ?    ; character cell width
  495. YCharSize    db    ?    ; character cell height
  496. NumberOfPlanes    db    ?    ; number of memory planes
  497. BitsPerPixel    db    ?    ; bits per pixel
  498. NumberOfBanks    db    ?    ; number of banks
  499. MemoryModel    db    ?    ; memory model type
  500. BankSize    db    ?    ; bank size in kb
  501.     db    227    DUP(?)    ; pad to 256 bytes
  502.     ENDS
  503.  
  504. vesabuf        db    256    DUP(?)
  505. modebuf        vesamode    ?
  506.  
  507.  
  508. MACRO    NEWBANK
  509.   call    [bankadr]
  510. ENDM
  511.  
  512.  
  513. ;*****
  514. ;***** initGraphics
  515. ;*****
  516.  
  517. PROC    C    initGraphics
  518.   cmp    [inited],0
  519.   je    @@NotInited
  520.   call    setMode
  521.   mov    ax,1
  522.   retf
  523.  
  524.     @@NotInited:
  525.   call    whichVGA
  526.   or    ax,ax                ; was function successful?
  527.   jz    @@Error                ; no, quit
  528.   call    setMode
  529.   or    ax,ax                ; was function successful?
  530.   jz    @@Error                     ; no, quit
  531.   call    makeAddrTable
  532.  
  533.   cmp    [vgamem],1024            ; ensure enough memory
  534.   jb    @@Error                ; abort if <1024 K of video RAM
  535.  
  536.   mov    ax,[bksize]            ; initialize bksizeShl10Dec
  537.   shl    ax,10                ; shift it
  538.   dec    ax                ; decrement it
  539.   mov    [bksizeShl10Dec],ax        ; store it
  540.  
  541.   mov    ax,1
  542.   mov    [inited],al
  543.   retf
  544.  
  545.     @@Error:
  546.   xor    ax,ax
  547.   retf
  548. ENDP
  549.  
  550.  
  551. ;*****
  552. ;***** putLine
  553. ;*****
  554.  
  555. PROC    C    putLine_scr_copy
  556.     ARG    lineNum:WORD, xOff:WORD, lineLen:WORD, buf:DATAPTR
  557.   push    ds si di
  558.  
  559.   cld
  560.   mov    bx,[lineNum]            ; Decide if bank changes mid-line
  561.   shl    bx,1
  562.   cmp    [cs:bankChanges+bx],0
  563.   jne    @@BankChanged
  564.  
  565.   mov    ax,[cs:bankNum+bx]
  566.   cmp    ax,[curBank]            ; set bank only if necessary
  567.   je    @@NoNewBank
  568.   NEWBANK
  569.  
  570.       @@NoNewBank:
  571.   mov    cx,[lineLen]            ; blast the line into video memory
  572.   mov    ax,0A000h
  573.   mov    es,ax
  574.   mov    di,[cs:lineOffs+bx]
  575.   add    di,[xOff]
  576.   lds    si,[buf]
  577.   shr    cx,1
  578.   rep    movsw
  579.   jnc    @@Exit
  580.   movsb
  581.       @@Exit:
  582.   pop    di si ds
  583.   leave
  584.   retf
  585.  
  586.       @@BankChanged:                  ; slow pixel-by-pixel
  587.   mov    cx,[lineLen]
  588.   mov    dx,[lineNum]
  589.   mov    bx,[xOff]
  590.   lds    si,[buf]
  591.     @@Loop:
  592.   lodsb
  593.   push    bx cx dx si
  594.   call    far putPixel_scr_copy C,bx,dx,ax
  595.   pop    si dx cx bx
  596.   inc    bx
  597.   loop    @@Loop
  598.  
  599.   pop    di si ds
  600.   leave
  601.   retf
  602. ENDP
  603.  
  604. PROC    C    putLine_mem_copy
  605.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DATAPTR
  606.   push    ds si di            ; save these registers
  607.  
  608.   xor    eax,eax                ; clear EAX
  609.   xor    edx,edx                ; clear EDX
  610.   xor    edi,edi                ; clear EDI
  611.  
  612.   les    di,[outAddr]            ; load output address
  613.   mov    ax,[y]
  614.   mov    dx,[outScreenWide]
  615.   mul    edx                    ; EDX:EAX = offset - EDI - x
  616.   add    edi,eax                ; EDI = offset - x
  617.   mov    dx,[xOff]
  618.   add    edi,edx                ; EDI = offset
  619.   mov    edx,edi                ; EDX = offset
  620.   shr    edx,4                ; EDX = # of paragraphs (segments)
  621.   add    dx,[outSeg]            ; DX = new segment
  622.   mov    es,dx                ; ES = new segment
  623.   and    di,0000000000001111b             ; DI = offset within new segment
  624.  
  625.   lds    si,[buf]            ; load input address
  626.   mov    dx,si                ; DX = offset
  627.   shr    dx,4                ; DX = # of paragraphs (segments)
  628.   mov    ax,ds                ; AX = DS
  629.   add    ax,dx                ; AX = new DS
  630.   mov    ds,ax                ; DS = new DS
  631.   and    si,0000000000001111b        ; SI = offset within new segment
  632.  
  633.   cld
  634.   mov    cx,[lineLen]            ; CX = line length
  635.   mov    dx,cx                ; DX = line length
  636.   shr    cx,2                ; CX = line length in dwords
  637.   rep    movsd                     ; move the dwords if necessary
  638.   mov    cx,dx                ; CX = line length in bytes
  639.   and    cx,0000000000000011b        ; CX = any residual bytes
  640.   rep    movsb                ; move the bytes if necessary
  641.  
  642.   pop    di si ds            ; restore registers
  643.   leave                    ; clean up
  644.   retf                    ; return
  645. ENDP
  646.  
  647.  
  648. ;*****
  649. ;***** getLine
  650. ;*****
  651.  
  652. PROC    C    getLine_scr
  653.     ARG    lineNum:WORD, xOff:WORD, lineLen:WORD, buf:DATAPTR
  654.   push    ds si di
  655.  
  656.   cld
  657.   mov    bx,[lineNum]            ; Decide if bank changes mid-line
  658.   shl    bx,1
  659.   cmp    [cs:bankChanges+bx],0
  660.   jne    @@BankChanged
  661.  
  662.   mov    ax,[cs:bankNum+bx]
  663.   cmp    ax,[curBank]            ; set bank only if necessary
  664.   je    @@NoNewBank
  665.   NEWBANK
  666.  
  667.     @@NoNewBank:
  668.   mov    cx,[lineLen]            ; blast the line into video memory
  669.   mov    ax,0A000h
  670.   mov    ds,ax
  671.   mov    si,[cs:lineOffs+bx]
  672.   add    si,[xOff]
  673.   les    di,[buf]
  674.   shr    cx,1
  675.   rep    movsw
  676.   jnc    @@Exit
  677.   movsb
  678.     @@Exit:
  679.   pop    di si ds
  680.   leave
  681.   retf
  682.  
  683.     @@BankChanged:                  ; slow pixel-by-pixel
  684.   mov    cx,[lineLen]
  685.   mov    dx,[lineNum]
  686.   mov    bx,[xOff]
  687.   les    di,[buf]
  688.     @@Loop:
  689.   push    bx cx dx di es
  690.   call    far getPixel_scr C,bx,dx
  691.   pop    es di dx cx bx
  692.   stosb
  693.   inc    bx
  694.   loop    @@Loop
  695.  
  696.   pop    di si ds
  697.   leave
  698.   retf
  699. ENDP
  700.  
  701. PROC    C    getLine_mem
  702.     ARG    y:WORD, xOff:WORD, lineLen:WORD, buf:DATAPTR
  703.   push    ds si di            ; save these registers
  704.  
  705.   xor    eax,eax                ; clear EAX
  706.   xor    edx,edx                ; clear EDX
  707.   xor    esi,esi                ; clear ESI
  708.  
  709.   les    si,[inAddr]            ; load input address
  710.   mov    ax,[y]
  711.   mov    dx,[inScreenWide]
  712.   mul    edx                    ; EDX:EAX = offset - ESI - x
  713.   add    esi,eax                ; ESI = offset - x
  714.   mov    dx,[xOff]
  715.   add    esi,edx                ; ESI = offset
  716.   mov    edx,esi                ; EDX = offset
  717.   shr    edx,4                ; EDX = # of paragraphs (segments)
  718.   add    dx,[inSeg]            ; DX = new segment
  719.   mov    ds,dx                ; ES = new segment
  720.   and    si,0000000000001111b             ; SI = offset within new segment
  721.  
  722.   les    di,[buf]            ; load output address
  723.   mov    dx,di                ; DX = offset
  724.   shr    dx,4                ; DX = # of paragraphs (segments)
  725.   mov    ax,es                ; AX = ES
  726.   add    ax,dx                ; AX = new ES
  727.   mov    es,ax                ; ES = new ES
  728.   and    di,0000000000001111b        ; DI = offset within new segment
  729.  
  730.   cld
  731.   mov    cx,[lineLen]            ; CX = line length
  732.   mov    dx,cx                ; DX = line length
  733.   shr    cx,2                ; CX = line length in dwords
  734.   rep    movsd                     ; move the dwords if necessary
  735.   mov    cx,dx                ; CX = line length in bytes
  736.   and    cx,0000000000000011b        ; CX = any residual bytes
  737.   rep    movsb                ; move the bytes if necessary
  738.  
  739.   pop    di si ds            ; restore registers
  740.   leave                    ; clean up
  741.   retf                    ; return
  742. ENDP
  743.  
  744.  
  745. ;*****
  746. ;***** putPixel
  747. ;*****
  748.  
  749. ; Copy a pixel to the screen
  750. PROC    C    putPixel_scr_copy
  751.     ARG    x:WORD, y:WORD, colour:BYTE
  752.   mov    bx,[y]                ; BX = y coordinate
  753.   shl    bx,1                ; to access a table of words
  754.   mov    ax,[cs:bankNum+bx]        ; AX = bank at start of line
  755.   mov    bx,[cs:lineOffs+bx]        ; DX = offset at start of line
  756.   add    bx,[x]                ; BX = offset of pixel
  757.   adc    ax,0                ; in case of overflow, inc AX
  758.   mov    dx,[bksizeShl10Dec]        ; DX = bank size in bytes - 1
  759.   cmp    bx,dx                ; is offset > than bank size
  760.   jbe    @@offsetOK            ; no, proceed
  761.  
  762.   sub    bx,dx                ; BX = fixed offset
  763.   inc    ax                ; AX = new bank
  764.  
  765.     @@offsetOK:
  766.   cmp    ax,[curBank]
  767.   je    @@NoNew
  768.   NEWBANK                ; switch banks if a new bank entered
  769.     @@NoNew:
  770.   mov    ax,0A000h            ; setup screen segment A000
  771.   mov    es,ax
  772.   mov    al,[colour]            ; get color of pixel to plot
  773.   mov    [es:bx],al
  774.   leave
  775.   retf
  776. ENDP
  777.  
  778. ; Copy a pixel to memory
  779. PROC    C    putPixel_mem_copy
  780.     ARG    x:WORD,y:WORD,colour:BYTE
  781.   xor    eax,eax                ; clear EAX
  782.   xor    ebx,ebx                ; clear EBX
  783.   xor    edx,edx                ; clear EDX
  784.  
  785.   les    bx,[outAddr]            ; load output address
  786.   mov    ax,[y]
  787.   mov    dx,[outScreenWide]
  788.   mul    edx                    ; EDX:EAX = offset - EBX - x
  789.   add    ebx,eax                ; EBX = offset - x
  790.   mov    dx,[x]
  791.   add    ebx,edx                ; EBX = offset
  792.  
  793.   mov    edx,ebx                ; EDX = offset
  794.   shr    edx,4                ; EDX = # of paragraphs (segments)
  795.   add    dx,[outSeg]            ; DX = new segment
  796.   mov    es,dx                ; ES = new segment
  797.   and    bx,0000000000001111b             ; BX = offset within new segment
  798.  
  799.   mov    al,[colour]            ; colour in AL
  800.   mov    [es:bx],al            ; store pixel
  801.   leave                    ; clean up
  802.   retf                    ; return
  803. ENDP
  804.  
  805. ; AND a pixel to memory
  806. PROC    C    putPixel_mem_and
  807.     ARG    x:WORD,y:WORD,colour:BYTE
  808.   xor    eax,eax                ; clear EAX
  809.   xor    ebx,ebx                ; clear EBX
  810.   xor    edx,edx                ; clear EDX
  811.  
  812.   les    bx,[outAddr]            ; load output address
  813.   mov    ax,[y]
  814.   mov    dx,[outScreenWide]
  815.   mul    edx                    ; EDX:EAX = offset - EBX - x
  816.   add    ebx,eax                ; EBX = offset - x
  817.   mov    dx,[x]
  818.   add    ebx,edx                ; EBX = offset
  819.  
  820.   mov    edx,ebx                ; EDX = offset
  821.   shr    edx,4                ; EDX = # of paragraphs (segments)
  822.   add    dx,[outSeg]            ; DX = new segment
  823.   mov    es,dx                ; ES = new segment
  824.   and    bx,0000000000001111b             ; BX = offset within new segment
  825.  
  826.   mov    al,[colour]            ; colour in AL
  827.   and    [es:bx],al            ; AND pixel
  828.   leave                    ; clean up
  829.   retf                    ; return
  830. ENDP
  831.  
  832. ; NOT a pixel to memory
  833. PROC    C    putPixel_mem_not
  834.     ARG    x:WORD,y:WORD,colour:BYTE
  835.   xor    eax,eax                ; clear EAX
  836.   xor    ebx,ebx                ; clear EBX
  837.   xor    edx,edx                ; clear EDX
  838.  
  839.   les    bx,[outAddr]            ; load output address
  840.   mov    ax,[y]
  841.   mov    dx,[outScreenWide]
  842.   mul    edx                    ; EDX:EAX = offset - EBX - x
  843.   add    ebx,eax                ; EBX = offset - x
  844.   mov    dx,[x]
  845.   add    ebx,edx                ; EBX = offset
  846.  
  847.   mov    edx,ebx                ; EDX = offset
  848.   shr    edx,4                ; EDX = # of paragraphs (segments)
  849.   add    dx,[outSeg]            ; DX = new segment
  850.   mov    es,dx                ; ES = new segment
  851.   and    bx,0000000000001111b             ; BX = offset within new segment
  852.  
  853.   mov    al,[colour]            ; colour in AL
  854.   not    al                ; NOT it
  855.   mov    [es:bx],al            ; store NOTed pixel
  856.   leave                    ; clean up
  857.   retf                    ; return
  858. ENDP
  859.  
  860. ; OR a pixel to memory
  861. PROC    C    putPixel_mem_or
  862.     ARG    x:WORD,y:WORD,colour:BYTE
  863.   xor    eax,eax                ; clear EAX
  864.   xor    ebx,ebx                ; clear EBX
  865.   xor    edx,edx                ; clear EDX
  866.  
  867.   les    bx,[outAddr]            ; load output address
  868.   mov    ax,[y]
  869.   mov    dx,[outScreenWide]
  870.   mul    edx                    ; EDX:EAX = offset - EBX - x
  871.   add    ebx,eax                ; EBX = offset - x
  872.   mov    dx,[x]
  873.   add    ebx,edx                ; EBX = offset
  874.  
  875.   mov    edx,ebx                ; EDX = offset
  876.   shr    edx,4                ; EDX = # of paragraphs (segments)
  877.   add    dx,[outSeg]            ; DX = new segment
  878.   mov    es,dx                ; ES = new segment
  879.   and    bx,0000000000001111b             ; BX = offset within new segment
  880.  
  881.   mov    al,[colour]            ; colour in AL
  882.   or    [es:bx],al            ; OR pixel
  883.   leave                    ; clean up
  884.   retf                    ; return
  885. ENDP
  886.  
  887. ; XOR a pixel to memory
  888. PROC    C    putPixel_mem_xor
  889.     ARG    x:WORD,y:WORD,colour:BYTE
  890.   xor    eax,eax                ; clear EAX
  891.   xor    ebx,ebx                ; clear EBX
  892.   xor    edx,edx                ; clear EDX
  893.  
  894.   les    bx,[outAddr]            ; load output address
  895.   mov    ax,[y]
  896.   mov    dx,[outScreenWide]
  897.   mul    edx                    ; EDX:EAX = offset - EBX - x
  898.   add    ebx,eax                ; EBX = offset - x
  899.   mov    dx,[x]
  900.   add    ebx,edx                ; EBX = offset
  901.  
  902.   mov    edx,ebx                ; EDX = offset
  903.   shr    edx,4                ; EDX = # of paragraphs (segments)
  904.   add    dx,[outSeg]            ; DX = new segment
  905.   mov    es,dx                ; ES = new segment
  906.   and    bx,0000000000001111b             ; BX = offset within new segment
  907.  
  908.   mov    al,[colour]            ; colour in AL
  909.   xor    [es:bx],al            ; XOR pixel
  910.   leave                    ; clean up
  911.   retf                    ; return
  912. ENDP
  913.  
  914.  
  915. ;*****
  916. ;***** getPixel
  917. ;*****
  918.  
  919. ; Get a pixel from the screen
  920. PROC    C    getPixel_scr
  921.     ARG    x:WORD, y:WORD
  922.   mov    bx,[y]                ; BX = y coordinate
  923.   shl    bx,1                ; to access a table of words
  924.   mov    ax,[cs:bankNum+bx]        ; AX = bank at start of line
  925.   mov    bx,[cs:lineOffs+bx]        ; DX = offset at start of line
  926.   add    bx,[x]                ; BX = offset of pixel
  927.   adc    ax,0                ; in case of overflow, inc AX
  928.   mov    dx,[bksizeShl10Dec]        ; DX = bank size in bytes - 1
  929.   cmp    bx,dx                ; is offset > than bank size
  930.   jb    @@offsetOK            ; no, proceed
  931.  
  932.   sub    bx,dx                ; BX = fixed offset
  933.   inc    ax                ; AX = new bank
  934.  
  935.     @@offsetOK:
  936.   cmp    ax,[curBank]
  937.   je    @@NoNew
  938.   NEWBANK                ; switch banks if a new bank entered
  939.     @@NoNew:
  940.   mov    ax,0A000h            ; setup screen segment A000
  941.   mov    es,ax
  942.   mov    al,[es:bx]            ; AL = colour for return
  943.   leave
  944.   retf
  945. ENDP
  946.  
  947. ; Get a pixel from memory
  948. PROC    C    getPixel_mem
  949.     ARG    x:WORD,y:WORD
  950.   xor    eax,eax                ; clear EAX
  951.   xor    ebx,ebx                ; clear EBX
  952.   xor    edx,edx                ; clear EDX
  953.  
  954.   les    bx,[inAddr]            ; load input address
  955.   mov    ax,[y]
  956.   mov    dx,[inScreenWide]
  957.   mul    edx                    ; EDX:EAX = offset - EBX - x
  958.   add    ebx,eax                ; EBX = offset - x
  959.   mov    dx,[x]
  960.   add    ebx,edx                ; EBX = offset
  961.  
  962.   mov    edx,ebx                ; EDX = offset
  963.   shr    edx,4                ; EDX = # of paragraphs (segments)
  964.   add    dx,[inSeg]            ; DX = new segment
  965.   mov    es,dx                ; ES = new segment
  966.   and    bx,0000000000001111b             ; BX = offset within new segment
  967.  
  968.   xor    ax,ax                ; clear AX
  969.   mov    al,[es:bx]            ; store pixel in AX for return
  970.   leave                    ; clean up
  971.   retf                    ; return
  972. ENDP
  973.  
  974.  
  975. ;*****
  976. ;***** horizLine
  977. ;*****
  978.  
  979. PROC    C    horizLine_scr_copy
  980.     ARG    y:WORD, x1:WORD, x2:WORD, colour:BYTE
  981.   push    di
  982.  
  983.   cld
  984.   mov    bx,[y]                ; Decide if bank changes mid-line
  985.   shl    bx,1
  986.   cmp    [cs:bankChanges+bx],0
  987.   jne    @@BankChanged
  988.  
  989.   mov    ax,[cs:bankNum+bx]
  990.   cmp    ax,[curBank]            ; set bank only if necessary
  991.   je    @@NoNewBank
  992.   NEWBANK
  993.  
  994.     @@NoNewBank:
  995.   mov    ax,0A000h
  996.   mov    es,ax
  997.   mov    ax,[x1]
  998.   mov    di,[cs:lineOffs+bx]
  999.   add    di,ax
  1000.   mov    cx,[x2]                ; blast the line into video memory
  1001.   inc    cx
  1002.   sub    cx,ax
  1003.   mov    al,[colour]
  1004.   mov    ah,al
  1005.   shr    cx,1
  1006.   rep    stosw
  1007.   jnc    @@Exit
  1008.   stosb
  1009.  
  1010.     @@Exit:
  1011.   pop    di
  1012.   leave
  1013.   retf
  1014.  
  1015.     @@BankChanged:                  ; slow pixel-by-pixel
  1016.   mov    bx,[x1]
  1017.   mov    cx,[x2]
  1018.   inc    cx
  1019.   sub    cx,bx
  1020.   mov    dx,[y]
  1021.     @@Loop:
  1022.   push    bx cx dx
  1023.   mov    al,[colour]
  1024.   call    far putPixel_scr_copy C,bx,dx,ax
  1025.   pop    dx cx bx
  1026.   inc    bx
  1027.   loop    @@Loop
  1028.  
  1029.   pop    di
  1030.   leave
  1031.   retf
  1032. ENDP
  1033.  
  1034. PROC    C    horizLine_mem_copy
  1035.     ARG    y:WORD, x1:WORD, x2:WORD, colour:BYTE
  1036.   push    edi                ; store EDI
  1037.  
  1038.   xor    eax,eax                ; clear EAX
  1039.   xor    edi,edi                ; clear EDI
  1040.   xor    edx,edx                ; clear EDX
  1041.  
  1042.   les    di,[outAddr]            ; load output address
  1043.   mov    ax,[y]
  1044.   mov    dx,[outScreenWide]
  1045.   mul    edx                    ; EDX:EAX = offset - EDI - x
  1046.   add    edi,eax                ; EDI = offset - x
  1047.   mov    dx,[x1]
  1048.   add    edi,edx                ; EDI = offset
  1049.   mov    edx,edi                ; EDX = offset
  1050.   shr    edx,4                ; EDX = # of paragraphs (segments)
  1051.   add    dx,[outSeg]            ; DX = new segment
  1052.   mov    es,dx                ; ES = new segment
  1053.   and    di,0000000000001111b             ; DI = offset within new segment
  1054.  
  1055.   mov    al,[colour]            ; colour in AL
  1056.   mov    ah,al                ; colour in AH
  1057.   mov    bx,ax
  1058.   shl    eax,16
  1059.   mov    ax,bx                 ; colour in each byte of EAX
  1060.  
  1061.   mov    cx,[x2]
  1062.   sub    cx,[x1]
  1063.   inc    cx                ; CX = line length in pixels
  1064.   mov    dx,cx                ; DX = line length in bytes
  1065.  
  1066.   shr    cx,2                ; CX = line length in dwords
  1067.   rep    stosd                ; store four bytes at a time
  1068.   mov    cx,dx                ; CX = line length in pixels
  1069.   and    cx,0000000000000011b        ; CX = any remaining bytes
  1070.   rep    stosb                ; store the remaining bytes
  1071.  
  1072.   pop    edi                    ; restore EDI
  1073.   leave                    ; clean up
  1074.   retf                    ; return
  1075. ENDP
  1076.  
  1077.  
  1078. ;*****
  1079. ;***** setPaletteReg
  1080. ;*****
  1081.  
  1082. PROC    C    setPaletteReg
  1083.     ARG    palNum:WORD,red:BYTE,green:BYTE,blue:BYTE
  1084.   mov    bx,[palNum]
  1085.  
  1086.   mov    dx,3C8h                ; set for correct palette register
  1087.   mov    ax,[palNum]
  1088.   out    dx,al
  1089.   inc    dx
  1090.  
  1091.   mov    al,[red]            ; red
  1092.   shr    al,2
  1093.   jnc    @@L1
  1094.   cmp    al,63
  1095.   je    @@L1
  1096.   inc    al
  1097.     @@L1:
  1098.   out    dx,al
  1099.  
  1100.   mov    al,[green]            ; green
  1101.   shr    al,2
  1102.   jnc    @@L2
  1103.   cmp    al,63
  1104.   je    @@L2
  1105.   inc    al
  1106.     @@L2:
  1107.   out    dx,al
  1108.  
  1109.   mov    al,[blue]            ; blue
  1110.   shr    al,2
  1111.   jnc    @@L3
  1112.   cmp    al,63
  1113.   je    @@L3
  1114.   inc    al
  1115.     @@L3:
  1116.   out    dx,al
  1117.  
  1118.   leave
  1119.   retf
  1120. ENDP
  1121.  
  1122.  
  1123. ;*****
  1124. ;***** getPaletteReg
  1125. ;*****
  1126.  
  1127. PROC    C    getPaletteReg
  1128.     ARG    palNum:WORD,red:DATAPTR,green:DATAPTR,blue:DATAPTR
  1129.   push    ds si
  1130.  
  1131.   mov    dx,3C7h                ; set for correct palette register
  1132.   mov    ax,[palNum]
  1133.   out    dx,al
  1134.   mov    dx,3C9h
  1135.  
  1136.   in    al,dx                ; red
  1137.   lds    si,[red]
  1138.   shl    al,2
  1139.   mov    [ds:si],al
  1140.   in    al,dx                ; green
  1141.   lds    si,[green]
  1142.   shl    al,2
  1143.   mov    [ds:si],al
  1144.   in    al,dx                ; blue
  1145.   lds    si,[blue]
  1146.   shl    al,2
  1147.   mov    [ds:si],al
  1148.  
  1149.   pop    si ds
  1150.   leave
  1151.   retf
  1152. ENDP
  1153.  
  1154.  
  1155. ;*****
  1156. ;***** setBlockPalette
  1157. ;*****
  1158.  
  1159.     PUBLIC    C    setBlockPalette
  1160. PROC    C    setBlockPalette
  1161.     ARG    firstReg:WORD,lastReg:WORD,paletteData:DATAPTR
  1162.   push    ds si
  1163.  
  1164.   lds    si,[paletteData]        ; set up
  1165.   mov    dx,3C8h
  1166.   mov    ax,[firstReg]
  1167.   out    dx,al
  1168.   inc    dx
  1169.   mov    cx,[lastReg]            ; CX = number of registers
  1170.   sub    cx,ax
  1171.   inc    cx
  1172.   cld
  1173.  
  1174.     @@LLoop:
  1175.   lodsb            ; red
  1176.   shr    al,2
  1177.   jnc    @@L1
  1178.   cmp    al,63
  1179.   je    @@L1
  1180.   inc    al
  1181.     @@L1:
  1182.   out    dx,al
  1183.  
  1184.   lodsb            ; green
  1185.   shr    al,2
  1186.   jnc    @@L2
  1187.   cmp    al,63
  1188.   je    @@L2
  1189.   inc    al
  1190.     @@L2:
  1191.   out    dx,al
  1192.  
  1193.   lodsb            ; blue
  1194.   shr    al,2
  1195.   jnc    @@L3
  1196.   cmp    al,63
  1197.   je    @@L3
  1198.   inc    al
  1199.     @@L3:
  1200.   out    dx,al
  1201.  
  1202.   loop    @@LLoop
  1203.  
  1204.     @@LExit:
  1205.   pop    si ds
  1206.   leave
  1207.   retf
  1208. ENDP
  1209.  
  1210.  
  1211. ;*****
  1212. ;***** getBlockPalette
  1213. ;*****
  1214.  
  1215.     PUBLIC    C    getBlockPalette
  1216. PROC    C    getBlockPalette
  1217.     ARG    firstReg:WORD,lastReg:WORD,paletteData:DATAPTR
  1218.   push    di
  1219.  
  1220.   les    di,[paletteData]        ; set up
  1221.   mov    dx,3C7h
  1222.   mov    ax,[firstReg]
  1223.   out    dx,al
  1224.   mov    dx,3C9h
  1225.   mov    cx,[lastReg]            ; CX = number of registers
  1226.   sub    cx,ax
  1227.   inc    cx
  1228.   cld
  1229.  
  1230.     @@L1:
  1231.   in    al,dx
  1232.   shl    al,2
  1233.   stosb            ; red
  1234.   in    al,dx
  1235.   shl    al,2
  1236.   stosb            ; green
  1237.   in    al,dx
  1238.   shl    al,2
  1239.   stosb            ; blue
  1240.   loop    @@L1
  1241.  
  1242.     @@LExit:
  1243.   pop    di
  1244.   leave
  1245.   retf
  1246. ENDP
  1247.  
  1248.  
  1249. ;*****
  1250. ;***** Bank switching routines
  1251. ;*****
  1252.  
  1253. _aheadb:                ; Ahead Systems Ver B
  1254.   push    ax dx cx
  1255.   cli
  1256.   mov    [curBank],ax
  1257.   mov    ch,al
  1258.   mov    dx,3CEh            ; Enable extended registers
  1259.   mov    ax,200Fh
  1260.   out    dx,ax
  1261.   mov    ah,ch
  1262.   mov    cl,4
  1263.   shl    ah,cl
  1264.   or    ah,ch
  1265.   mov    al,0Dh
  1266.   out    dx,ax
  1267.   sti
  1268.   pop    cx dx ax
  1269.   ret
  1270.  
  1271. _ativga:                ; ATI VGA Wonder
  1272.   push    ax dx
  1273.   cli
  1274.   mov    [curBank],ax
  1275.   mov    ah,al
  1276.   mov    dx,1CEh
  1277.   mov    al,0B2h
  1278.   out    dx,al
  1279.   inc    dl
  1280.   in    al,dx
  1281.   shl    ah,1
  1282.   and    al,0E1h
  1283.   or    ah,al
  1284.   mov    al,0B2h
  1285.   dec    dl
  1286.   out    dx,ax
  1287.   sti
  1288.   pop    dx ax
  1289.   ret
  1290.  
  1291. _chipstech:                ; Chips & Tech
  1292.   push    ax dx ax
  1293.   cli
  1294.   mov    [curBank],ax
  1295.   mov    dx,46E8h        ; place chip in setup mode
  1296.   mov    ax,1Eh
  1297.   out    dx,ax
  1298.   mov    dx,103h            ; enable extended registers
  1299.   mov    ax,0080h
  1300.   out    dx,ax
  1301.   mov    dx,46E8h        ; bring chip out of setup mode
  1302.   mov    ax,0Eh
  1303.   out    dx,ax
  1304.   pop    ax
  1305.   mov    ah,al
  1306.   mov    al,10h
  1307.   mov    dx,3D6h
  1308.   out    dx,ax
  1309.   sti
  1310.   pop    dx ax
  1311.   ret
  1312.  
  1313. _everex:                ; Everex
  1314.   push    ax dx cx
  1315.   cli
  1316.   mov    [curBank],ax
  1317.   mov    cl,al
  1318.   mov    dx,3C4h
  1319.   mov    al,8
  1320.   out    dx,al
  1321.   inc    dl
  1322.   in    al,dx
  1323.   dec    dl
  1324.   shl    al,1
  1325.   shr    cl,1
  1326.   rcr    al,1
  1327.   mov    ah,al
  1328.   mov    al,8
  1329.   out    dx,ax
  1330.   mov    dl,0CCh
  1331.   in    al,dx
  1332.   mov    dl,0C2h
  1333.   and    al,0DFh
  1334.   shr    cl,1
  1335.   jc    @@nob2
  1336.   or    al,20h
  1337.       @@nob2:
  1338.   out    dx,al
  1339.   sti
  1340.   pop    cx dx ax
  1341.   ret
  1342.  
  1343. _oak067:                ; Oak Technology Inc OTI-067
  1344.   push    ax dx
  1345.   cli
  1346.   mov    [curBank],ax
  1347.   and    al,15
  1348.   mov    ah,al
  1349.   shl    al,4
  1350.   or    ah,al
  1351.   mov    al,11h
  1352.   mov    dx,3DEh
  1353.   out    dx,ax
  1354.   sti
  1355.   pop    dx ax
  1356.   ret
  1357.  
  1358. _t8900:                    ; Trident 8900
  1359.   push    ax dx ax
  1360.   cli
  1361.   mov    [curBank],ax
  1362.   mov    dx,3CEh            ; set pagesize to 64k
  1363.   mov    al,6
  1364.   out    dx,al
  1365.   inc    dl
  1366.   in    al,dx
  1367.   dec    dl
  1368.   or    al,4
  1369.   mov    ah,al
  1370.   mov    al,6
  1371.   out    dx,ax
  1372.  
  1373.   mov    dl,0C4h            ; switch to BPS mode
  1374.   mov    al,0Bh
  1375.   out    dx,al
  1376.   inc    dl
  1377.   in    al,dx
  1378.   dec    dl
  1379.  
  1380.   pop    ax
  1381.   mov    ah,al
  1382.   xor    ah,2
  1383.   mov    dx,3C4h
  1384.   mov    al,0Eh
  1385.   out    dx,ax
  1386.   sti
  1387.   pop    dx ax
  1388.   ret
  1389.  
  1390. _tseng4:                ; Tseng 4000 series
  1391.   push    ax dx
  1392.   cli
  1393.   mov    [curBank],ax
  1394.   mov    ah,al
  1395.   mov    dx,3BFh            ; Enable access to extended registers
  1396.   mov    al,3
  1397.   out    dx,al
  1398.   mov    dl,0D8h
  1399.   mov    al,0A0h
  1400.   out    dx,al
  1401.   and    ah,15
  1402.   mov    al,ah
  1403.   shl    al,4
  1404.   or    al,ah
  1405.   mov    dl,0CDh
  1406.   out    dx,al
  1407.   sti
  1408.   pop    dx ax
  1409.   ret
  1410.  
  1411. _vesa:                ; Vesa SVGA interface
  1412.   push    ax bx dx
  1413.   cli
  1414.   mov    [curBank],ax
  1415.   mov    dx,ax
  1416.   xor    bx,bx
  1417.   mov    ax,4F05h
  1418.   int    10h
  1419.   sti
  1420.   pop    dx bx ax
  1421.   ret
  1422.  
  1423. _nobank:
  1424.   cli
  1425.   mov    [curBank],ax
  1426.   sti
  1427.   ret
  1428.  
  1429.  
  1430. MACRO    BKADR    func
  1431.   mov    [func],1
  1432.   mov    [bankadr],OFFSET _&func
  1433. ENDM
  1434.  
  1435. MACRO    NOJMP
  1436.   local    lbl
  1437.   jmp    short    lbl
  1438.     lbl:
  1439. ENDM
  1440.  
  1441.  
  1442. PROC    whichVGA    NEAR
  1443.   push    si di
  1444.  
  1445.   cmp    [inited],1
  1446.   jne    @@goTest
  1447.   mov    ax,[retval]
  1448.   pop    di si
  1449.   ret
  1450.  
  1451.     @@goTest:
  1452.   mov    [bankadr],OFFSET _nobank
  1453.   mov    [vgamem],256
  1454.   mov    [bksize],64
  1455.   xor    ax,ax
  1456.   mov    [curBank],ax
  1457.   mov    [aheadb],ax
  1458.   mov    [ativga],ax
  1459.   mov    [everex],ax
  1460.   mov    [t8900],ax
  1461.   mov    [tseng4],ax
  1462.   mov    [vesa],ax
  1463.  
  1464.   mov    si,1                ; success code; changed on error
  1465.  
  1466.   mov    ax,cs                ; Test for VESA
  1467.   mov    es,ax
  1468.   mov    di,OFFSET vesabuf
  1469.   mov    ax,4F00h
  1470.   int    10h
  1471.   cmp    ax,004Fh
  1472.   jne    @@noVESA
  1473.   BKADR    vesa
  1474.   mov    [bksize],64            ; assume 64 K bank size (for now)
  1475.   mov    [vgamem],1024            ; assume 1024 K if VESA
  1476.   jmp    @@fini
  1477.  
  1478.     @@noVESA:
  1479.   mov    ax,0C000h            ; Test for ATI
  1480.   mov    es,ax
  1481.   cmp    [word ptr es:40h],'13'    ; ATI Signiture on the Video BIOS
  1482.   jnz    @@noATI
  1483.   BKADR    ativga
  1484.   mov    [bksize],64        ; 64K bank size
  1485.   mov    dx,[es:10h]        ; get value of ATI extended register
  1486.   mov    bl,[es:43h]        ; get value of ATI chip version
  1487.   cmp    bl,'3'
  1488.   jae    @@v6up            ; use different method to find memory size
  1489.   mov    al,0BBh
  1490.   cli
  1491.   out    dx,al
  1492.   inc    dx
  1493.   in    al,dx
  1494.   sti
  1495.   test    al,20h
  1496.   jz    @@no512
  1497.   mov    [vgamem],512
  1498.   jmp    short    @@no512
  1499.       @@v6up:
  1500.   mov    al,0B0h            ; method for newer ATIs
  1501.   cli
  1502.   out    dx,al
  1503.   inc    dx
  1504.   in    al,dx            ; get RAM size for versions 3-5
  1505.   sti
  1506.   test    al,10h            ; check if 256 K or 512 K
  1507.   jz    @@v7up
  1508.   mov    [vgamem],512
  1509.       @@v7up:
  1510.   cmp    bl,'4'            ; get RAM size for versions 4 & 5
  1511.   jb    @@no512
  1512.   test    al,8            ; check if version 5 chip has 1024 K
  1513.   jz    @@no512
  1514.   mov    [vgamem],1024
  1515.       @@no512:
  1516.   jmp    @@fini
  1517.  
  1518.     @@noATI:
  1519.   mov    ax,7000h            ; Test for Everex
  1520.   xor    bx,bx
  1521.   cld
  1522.   int    10h
  1523.   cmp    al,70h
  1524.   jnz    @@noEverex
  1525.   BKADR    everex
  1526.   mov    [bksize],64        ; 64 K bank size
  1527.   and    ch,10000000b        ; how much memory on board?
  1528.   jz    @@skp
  1529.   mov    [vgamem],1024
  1530.      @@skp:            ; fall through for Everex boards using Trident or Tseng4000
  1531.  
  1532.     @@noEverex:
  1533.   mov    ax,5F00h            ; Test for Chips & Tech
  1534.   xor    bx,bx
  1535.   cld
  1536.   int    10h
  1537.   cmp    al,5Fh
  1538.   jnz    @@noChipsTech
  1539.   BKADR    chipstech
  1540.   mov    [bksize],16        ; 16 K bank size
  1541.   cmp    bh,2
  1542.   jb    @@skp4
  1543.   mov    [vgamem],1024
  1544.     @@skp4:
  1545.   jmp    @@fini
  1546.  
  1547.     @@noChipsTech:
  1548.   mov    dx,3DEh                ; Test for Oak Technology
  1549.   mov    ax,0FF11h        ; look for bank switch register
  1550.   call    _isport2
  1551.   jnz    @@noOak
  1552.   BKADR    oak067
  1553.   mov    [bksize],64        ; 64 K bank size
  1554.   mov    al,0Dh
  1555.   out    dx,al
  1556.   inc    dx
  1557.   NOJMP
  1558.   in    al,dx
  1559.   test    al,11000000b
  1560.   jz    @@no4ram
  1561.   mov    [vgamem],512
  1562.   test    al,01000000b
  1563.   jz    @@no4ram
  1564.   mov    [vgamem],1024
  1565.       @@no4ram:
  1566.   jmp    @@fini
  1567.  
  1568.     @@noOak:
  1569.   mov    dx,3C4h                  ; Test for Trident
  1570.   mov    al,0Bh
  1571.   out    dx,al
  1572.   inc    dl
  1573.   in    al,dx
  1574.   and    al,0Fh
  1575.   cmp    al,06h
  1576.   ja    @@noTrident8900
  1577.   cmp    al,3
  1578.   jb       @@noTrident8900
  1579.   BKADR    t8900            ; Trident 8900 found
  1580.   mov    [bksize],64
  1581.   mov    dx,3D5h
  1582.   mov    al,1Fh
  1583.   out    dx,al
  1584.   inc    dx
  1585.   in    al,dx
  1586.   and    al,3
  1587.   cmp    al,1
  1588.   jb    @@notmem
  1589.   mov    [vgamem],512
  1590.   je    @@notmem
  1591.   mov    [vgamem],1024
  1592.     @@notmem:
  1593.   jmp    @@fini
  1594.  
  1595.     @@noTrident8900:
  1596.   xor    ch,ch                ; check for Tseng 4000 series
  1597.   mov    dx,3D4h
  1598.   mov    ax,0F33h
  1599.   call    _isport2
  1600.   jnz    @@noTseng4
  1601.   mov    ch,1
  1602.  
  1603.   mov    dx,3BFh            ; Enable access to extended registers
  1604.   mov    al,3
  1605.   out    dx,al
  1606.   mov    dx,3D8h
  1607.   mov    al,0A0h
  1608.   out    dx,al
  1609.   jmp    short @@yes4
  1610.  
  1611.     @@noTseng4:
  1612.   mov    dx,3D4h            ; Test for Tseng 3000 or 4000
  1613.   mov    ax,1F25h        ; is the Overflow High register there?
  1614.   call    _isport2
  1615.   jnz    @@noTseng
  1616.   mov    al,03Fh            ; bottom six bits only
  1617.   jmp    short @@yes3
  1618.     @@yes4:
  1619.   mov    al,0FFh
  1620.     @@yes3:
  1621.   mov    dx,3CDh            ; test bank switch register
  1622.   call    _isport1
  1623.   jnz    @@noTseng
  1624.   mov    [bksize],64        ; 64 K bank size
  1625.   or    ch,ch
  1626.   jnz    @@t4mem
  1627.   mov    [vgamem],512
  1628.   jmp    @@fini
  1629.  
  1630.     @@t4mem:
  1631.   mov    dx,3D4h            ; Tseng 4000 memory detect 1meg
  1632.   mov    al,37h
  1633.   out    dx,al
  1634.   inc    dx
  1635.   in    al,dx
  1636.   test    al,1000b        ; if using 64kx4 RAMs then no more than 256k
  1637.   jz    @@nomem
  1638.   and    al,3
  1639.   cmp    al,1            ; if 8 bit wide bus then only two 256kx4 RAMs
  1640.   jbe    @@nomem
  1641.   mov    [vgamem],512
  1642.   cmp    al,2            ; if 16 bit wide bus then four 256kx4 RAMs
  1643.   je    @@nomem
  1644.   mov    [vgamem],1024        ; full meg with eight 256kx4 RAMs
  1645.     @@nomem:
  1646.   BKADR    tseng4
  1647.   mov    [bksize],64        ; 64 K bank size
  1648.   jmp    @@fini
  1649.  
  1650.     @@noTseng:
  1651.   mov    dx,3CEh                ; Test for Above B chipset
  1652.   mov    ax,200Fh
  1653.   out    dx,ax
  1654.   inc    dx
  1655.   NOJMP
  1656.   in    al,dx
  1657.   cmp    al,21h
  1658.   jne    @@fini
  1659.   BKADR    aheadb
  1660.   mov    [bksize],64        ; 64 K bank size
  1661.   mov    [vgamem],512
  1662.   jmp   @@fini
  1663.  
  1664.       @@noSVGA:
  1665.   xor    si,si                ; set error flag
  1666.  
  1667.     @@fini:
  1668.   mov    ax,si                ; success code in AX for return
  1669.   mov    [retval],ax
  1670.   pop    di si
  1671.   ret
  1672. ENDP
  1673.  
  1674.  
  1675. PROC    _chkbk    NEAR            ; bank switch check routine
  1676.   mov    di,0B800h
  1677.   mov    es,di
  1678.   xor    di,di
  1679.   mov    bx,1234h
  1680.   call    _gochk
  1681.   jnz    @@badchk
  1682.   mov    bx,4321h
  1683.   call    _gochk
  1684.   jnz    @@badchk
  1685.   clc
  1686.   ret
  1687.     @@badchk:
  1688.   stc
  1689.   ret
  1690. ENDP
  1691.  
  1692.  
  1693. PROC    _gochk    NEAR
  1694.   push    si
  1695.   mov    si,bx
  1696.  
  1697.   mov    al,cl
  1698.   call    dx
  1699.   xchg    bl,[es:di]
  1700.   mov    al,ch
  1701.   call    dx
  1702.   xchg    bh,[es:di]
  1703.  
  1704.   xchg    si,bx
  1705.  
  1706.   mov    al,cl
  1707.   call    dx
  1708.   xor    bl,[es:di]
  1709.   mov    al,ch
  1710.   call    dx
  1711.   xor    bh,[es:di]
  1712.  
  1713.   xchg    si,bx
  1714.  
  1715.   mov    al,ch
  1716.   call    dx
  1717.   mov    [es:di],bh
  1718.   mov    al,cl
  1719.   call    dx
  1720.   mov    [es:di],bl
  1721.  
  1722.   xor    al,al
  1723.   call    dx
  1724.   or    si,si
  1725.   pop    si
  1726.   ret
  1727. ENDP
  1728.  
  1729.  
  1730. PROC    _isport2    NEAR        ; check for valid I/O port
  1731.                     ; AL is index, AH is bit mask
  1732.   push    bx
  1733.   mov    bx,ax
  1734.   out    dx,al
  1735.   mov    ah,al
  1736.   inc    dx
  1737.   in    al,dx
  1738.   dec    dx
  1739.   xchg    al,ah
  1740.   push    ax
  1741.   mov    ax,bx
  1742.   out    dx,ax
  1743.   out    dx,al
  1744.   mov    ah,al
  1745.   inc    dx
  1746.   in    al,dx
  1747.   dec    dx
  1748.   and    al,bh
  1749.   cmp    al,bh
  1750.   jnz    @@noport
  1751.   mov    al,ah
  1752.   xor    ah,ah
  1753.   out    dx,ax
  1754.   out    dx,al
  1755.   mov    ah,al
  1756.   inc    dx
  1757.   in    al,dx
  1758.   dec    dx
  1759.   and    al,bh
  1760.   cmp    al,0
  1761.     @@noport:
  1762.   pop    ax
  1763.   out    dx,ax
  1764.   pop    bx
  1765.   ret
  1766. ENDP
  1767.  
  1768.  
  1769. PROC    _isport1    NEAR        ; check for valid I/O port
  1770.                     ; AL is bit mask
  1771.   mov    ah,al
  1772.   in    al,dx
  1773.   push    ax
  1774.   mov    al,ah
  1775.   out    dx,al
  1776.   in    al,dx
  1777.   and    al,ah
  1778.   cmp    al,ah
  1779.   jnz    @@noport
  1780.   xor    al,al
  1781.   out    dx,al
  1782.   in    al,dx
  1783.   and    al,ah
  1784.   cmp    al,0
  1785.     @@noport:
  1786.   pop    ax
  1787.   out    dx,al
  1788.   ret
  1789. ENDP
  1790.  
  1791.  
  1792. PROC    setMode    NEAR            ; Set 1024x768x256
  1793.   mov    ax,SCREEN_WIDE
  1794.   mov    [scanline],ax
  1795.  
  1796.   cmp    [vesa],0
  1797.   jz    @@noVESA
  1798.   mov    bx,105h
  1799.   call    VESAset
  1800.   or    ax,ax                ; was function successful?
  1801.   jz    @@noSVGA            ; no, quit
  1802.   jmp    @@godo2
  1803.       @@noVESA:
  1804.   cmp    [aheadb],0
  1805.   jz    @@noAbove
  1806.   mov    ax,63h
  1807.   jmp    short @@godo
  1808.     @@noAbove:
  1809.   cmp    [everex],0
  1810.   jz    @@noEverex
  1811.   mov    ax,70h
  1812.   mov    bl,32h
  1813.   jmp    short @@godo
  1814.     @@noEverex:
  1815.   cmp    [ativga],0
  1816.   jz    @@noATI
  1817.   mov    ax,64h
  1818.   jmp    short @@godo
  1819.     @@noATI:
  1820.   cmp    [oak067],0
  1821.   jz    @@noOak067
  1822.   mov    ax,59h
  1823.   jmp    short    @@godo
  1824.       @@noOak067:
  1825.   cmp    [t8900],0
  1826.   jz    @@noTrident8900
  1827.   mov    ax,62h
  1828.   jmp    short @@godo
  1829.     @@noTrident8900:
  1830.   cmp    [tseng4],0
  1831.   jz    @@noSVGA
  1832.   mov    ax,38h
  1833.  
  1834.     @@godo:
  1835.   int    10h
  1836.       @@godo2:
  1837.   mov    [curBank],-1
  1838.   mov    ax,1                ; return success code
  1839.   ret
  1840.  
  1841.     @@noSVGA:
  1842.   xor    ax,ax                ; return error code
  1843.   ret
  1844. ENDP
  1845.  
  1846.  
  1847. PROC    VESAset        NEAR
  1848.   push    di
  1849.  
  1850.   push    bx
  1851.   mov    ax,4F02h
  1852.   int    10h                   ; set the mode
  1853.   pop    cx
  1854.   or    ah,ah                ; was function successful?
  1855.   jz    @@noError            ; yes
  1856.   xor    ax,ax                ; set error code (for setMode)
  1857.   jmp    short    @@Exit
  1858.  
  1859.       @@noError:
  1860.   mov    ax,cs
  1861.   mov    es,ax
  1862.   mov    di,OFFSET modebuf
  1863.   mov    ax,4F01h
  1864.   int    10h                ; get the mode information
  1865.   mov    ax,[modebuf.WinSize]
  1866.   mov    [bksize],ax
  1867.   mov    ax,[modebuf.BytesPerLine]
  1868.   mov    [scanline],ax
  1869.   mov    ax,1                ; set success code (for setMode)
  1870.  
  1871.       @@Exit:
  1872.   pop    di
  1873.   ret
  1874. ENDP
  1875.  
  1876.  
  1877. PROC    makeAddrTable    NEAR
  1878.   LOCAL    temp:WORD
  1879.   push    si di
  1880.  
  1881.   mov    si,OFFSET lineOffs
  1882.   mov    di,OFFSET bankNum
  1883.   xor    bx,bx                ; current line number = 0
  1884.  
  1885.   mov    ax,[bksize]            ; separate process if bksize=64 K
  1886.   cmp    ax,64
  1887.   je    @@noBnk
  1888.  
  1889.   mov    cl,10
  1890.   shl    ax,cl                ; AX = bank size in bytes
  1891.   dec    ax
  1892.   mov    [temp],ax            ; [temp] = banksize in bytes - 1
  1893.   mov    cl,10
  1894.   mov    ax,[bksize]            ; AX = bank size in K
  1895.       @@shlp:
  1896.   inc    cl
  1897.   shr    ax,1
  1898.   jnz    @@shlp                ; loop until AX = 0
  1899.  
  1900.   xor    ax,ax                ; AX = 0
  1901.   xor    dx,dx                ; DX = 0
  1902.       @@lp:
  1903.   push    ax                ; store AX
  1904.   shr    ax,cl
  1905.   add    dx,ax                ; update current bank number
  1906.   pop    ax                ; restore AX
  1907.   and    ax,[temp]            ; mask offset so it's < bank size
  1908.   mov    [cs:si],ax            ; save line offset
  1909.   add    si,2                ; update pointer
  1910.   mov    [cs:di],dx            ; save bank number
  1911.   add    di,2                ; update pointer
  1912.   add    ax,[scanline]            ; update offset
  1913.   inc    bx                ; update line number
  1914.   cmp    bx,SCREEN_DEEP
  1915.   jb    @@lp                ; loop until all lines done
  1916.   jmp    short    @@calcBankChange    ; calculate bank change table
  1917.  
  1918.       @@noBnk:
  1919.   xor    ax,ax                ; AX = 0
  1920.   xor    dx,dx                ; DX = 0
  1921.   mov    cx,[scanline]            ; CX = width of line in bytes
  1922.       @@nlp:
  1923.   mov    [cs:si],ax            ; store line offset
  1924.   add    si,2                ; update pointer
  1925.   mov    [cs:di],dx            ; store bank number
  1926.   add    di,2                ; update pointer
  1927.   add    ax,cx                ; add another line width
  1928.   adc    dx,0                ; increase bank number if overflow
  1929.   inc    bx                ; update current line number
  1930.   cmp    bx,SCREEN_DEEP
  1931.   jb    @@nlp                ; jump until all lines done
  1932.  
  1933.       @@calcBankChange:
  1934.   mov    di,OFFSET bankChanges        ; initialize pointer
  1935.   xor    ax,ax                ; AX = current line
  1936.       @@bankChangeLoop:
  1937.   mov    bx,ax                ; BX = current line
  1938.   shl    bx,1                ; to access a table of words
  1939.   mov    dx,[cs:bankNum+bx]        ; DX = bank at start of current line
  1940.   mov    bx,ax                ; BX = current line
  1941.   inc    bx                ; BX = next line
  1942.   shl    bx,1                ; to access a table of words
  1943.   mov    cx,[cs:bankNum+bx]        ; CX = bank at start of next line
  1944.   mov    si,[cs:lineOffs+bx]        ; SI = offset at start of next line
  1945.   or    si,si                ; is SI=0?
  1946.   jz    @@L1                ; yes, jump
  1947.   dec    cx                ; CX = bank at end of current line
  1948.       @@L1:
  1949.   cmp    cx,dx                ; are start and end banks the same?
  1950.   jne    @@newBank            ; bank changed, jump
  1951.   mov    [word ptr cs:di],1        ; store bank changed flag
  1952.   jmp    short    @@L2            ; jump
  1953.       @@newBank:
  1954.   mov    [word ptr cs:di],0        ; store bank same flag
  1955.       @@L2:
  1956.   add    di,2                ; update pointer
  1957.   inc    ax                ; update current line number
  1958.   cmp    ax,SCREEN_DEEP
  1959.   jb    @@bankChangeLoop        ; loop until all lines done
  1960.  
  1961.   pop    di si
  1962.   ret
  1963. ENDP
  1964.  
  1965.  
  1966.     ENDS
  1967.  
  1968. END